﻿package org.leles.engines.octogame 
{
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	
	/**
	 * ...
	 * @author Bruno leles
	 */
	public class OctoGameEngine extends OctoGameObject
	{
		public static const R_LETTER_LOST:Number		= 0x000001;
		public static const R_LEVEL_FINISHED:Number		= 0x000002;
		
		private var _level:OctoGameLevel;
		private var _tentacles:Array/*of OctoGameTentacle*/
		private var _timer:Timer;
		private var _letterTimer:Timer;
		private var _state:Number = OctoGameEngineState.IDLE;
		
		//_________________________________________________________________________________________
		//                                                                       base event objects
		private var ev_gameStart:OctoGameEvent;
		private var ev_gameOver:OctoGameEvent;
		private var ev_phaseEntered:OctoGameEvent;
		private var ev_phaseFinished:OctoGameEvent;
		private var ev_letterPressed:OctoGameEvent;
		private var ev_letterTimesUp:OctoGameEvent;
		private var ev_tentacleReleased:OctoGameEvent;
		private var ev_tentacleJointed:OctoGameEvent;
		private var ev_stateChanged:OctoGameEvent;
		
		public function OctoGameEngine(frameRate:uint = 30)
		{
			super();
			_timer = new Timer( 1000 / frameRate);
			_timer.addEventListener( TimerEvent.TIMER, _timerHandler )
			
			_letterTimer = new Timer(0, 1);
			_letterTimer.addEventListener( TimerEvent.TIMER_COMPLETE, _letterTimerHandler );
			
			_tentacles = new Array();
			
			addEventListener( OctoGameEvent.GAME_START, _engine );
			addEventListener( OctoGameEvent.PHASE_ENTERED, _engine );
			//_____________________________________________________________________________________
			ev_gameStart		= new OctoGameEvent( OctoGameEvent.GAME_START );
			ev_gameOver			= new OctoGameEvent( OctoGameEvent.GAME_OVER );
			ev_phaseEntered		= new OctoGameEvent( OctoGameEvent.PHASE_ENTERED);
			ev_phaseFinished	= new OctoGameEvent( OctoGameEvent.PHASE_FINISHED);
			ev_letterPressed	= new OctoGameEvent( OctoGameEvent.LETTER_PRESSED);
			ev_letterTimesUp	= new OctoGameEvent( OctoGameEvent.LETTER_TIMESUP );
			ev_tentacleReleased	= new OctoGameEvent( OctoGameEvent.TENTACLE_RELEASED );
			ev_tentacleJointed	= new OctoGameEvent( OctoGameEvent.TENTACLE_JOINTED );
			ev_stateChanged		= new OctoGameEvent( OctoGameEvent.STATE_CHANGED );
		}
		
		private function _timerHandler(e:TimerEvent):void 
		{
			switch (e.type)
			{
				case TimerEvent.TIMER:
					
					break;
			}
		}
		
		private function _letterTimerHandler(e:TimerEvent):void 
		{
			switch (e.type) 
			{
				case TimerEvent.TIMER_COMPLETE:
					//gameOver(R_LETTER_LOST);
					letterTimesUp();
					break;
			}
		}
		
		public function letterTimesUp():void 
		{
			if ( isWaitingLetter )
			{
				//__________________________________________________
				//                                             event
				ev_letterTimesUp.level = _level;
				ev_letterTimesUp.phase = _level.currentPhase;
				ev_letterTimesUp.letter = _level.currentPhase.letter;
				dispatchEvent( ev_letterTimesUp.clone());
			}
		}
		
		public function start(level:OctoGameLevel = null):void
		{
			if ( level != null )
			{
				_level = level;
			}
			
			if ( _level.gotoFirstPhase() )
			{
				// checar tentaculos em cada phase;
				for ( var i:Object in _level.phases )
				{
					var tid:int = _level.getPhase(i as int).tentacle;
					if ( _tentacles[tid] == null ) _tentacles[tid] = new OctoGameTentacle();
				}
				
				state = OctoGameEngineState.WAITING_LETTER;
				//__________________________________________________
				//                                             event
				ev_gameStart.level = _level;
				ev_gameStart.phase = _level.currentPhase;
				ev_gameStart.letter = _level.currentPhase.letter;
				ev_gameStart.tentacle = getTentacle(_level.currentPhase.tentacle);
				dispatchEvent( ev_gameStart.clone() );
			}
		}
		
		public function gameOver(reason:Number):void 
		{
			state = OctoGameEngineState.IDLE;
			//__________________________________________________
			//                                             event
			ev_gameOver.reason = reason;
			dispatchEvent( ev_gameOver.clone() );
		}
		
		public function pressLetter(letter:String):void 
		{
			if ( isWaitingLetter )
			{
				//__________________________________________________
				//                                             event
				ev_letterPressed.letter = letter;
				ev_letterPressed.rightLetter = ( letter == _level.currentPhase.letter );
				dispatchEvent( ev_letterPressed.clone() );
				
				if( letter == _level.currentPhase.letter )
				{
					releaseTentacle( getTentacle( _level.currentPhase.tentacle ) );
					state = OctoGameEngineState.WAITING_TENTACLE;
				}
			}
		}
		
		public function releaseTentacle(tentacle:OctoGameTentacle):void 
		{
			//#preciso guardar esse tentaculo =D
			tentacle.released = true;
			
			//__________________________________________________
			//                                             event
			ev_tentacleReleased.tentacle = tentacle;
			ev_tentacleReleased.clone();
		}
		
		public function tentacleJointed(tentacle:OctoGameTentacle):void 
		{
			if ( isWaitingTentacle )
			{
				// encaixou o tentaculo ( acho q nao preciso saber onde necesariamente )
				// vamos para a proxima letra se existir... se nao ... acabamos o jogo
				if ( getTentacle(_level.currentPhase.tentacle) === tentacle )
				{
					tentacle.released = false;
					
					if ( _level.gotoNextPhase() )
					{
						// vamos para a proxima phase
						
						//__________________________________________________
						//                                             event
						ev_phaseEntered.phase = _level.currentPhase;
						dispatchEvent(ev_phaseEntered.clone());
					}
					else
					{
						// fim de jogo
						gameOver( R_LEVEL_FINISHED );
					}
				}
			}
		}
		
		private function _engine(e:OctoGameEvent):void 
		{
			switch (e.type) 
			{
				case OctoGameEvent.GAME_START:
				case OctoGameEvent.PHASE_ENTERED:
					_letterTimer.delay = _level.currentPhase.time;
					_letterTimer.start();
					break;
			}
		}
		
		public function getTentacle(index:Number):OctoGameTentacle
		{
			return _tentacles[index] as OctoGameTentacle;
		}
		
		public function get isWaitingLetter():Boolean { return (_state & OctoGameEngineState.WAITING_LETTER) != 0; }
		public function get isWaitingTentacle():Boolean { return (_state & OctoGameEngineState.WAITING_TENTACLE) != 0; }
		
		public function get state():Number { return _state; }
		
		public function set state(value:Number):void 
		{
			if (_state == value) return;
			_state = value;
			
			//__________________________________________________
			//                                             event
			ev_stateChanged.state = _state;
			dispatchEvent( ev_stateChanged.clone() );
		}
	}
	
}